package com.ruicar.afs.cloud.workflow.greatwall.processor.impl.msg;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.dynamicrequest.DynamicRequest;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.AfsFlowQueryRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.UserOnlineRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.UserOnlineResponse;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.response.FLowNodeUserBean;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.response.FlowInstanceBean;
import com.ruicar.afs.cloud.workflow.api.util.FlowMappingHelper;
import com.ruicar.afs.cloud.workflow.greatwall.dto.GwtFlowEngineResponse;
import com.ruicar.afs.cloud.workflow.greatwall.dto.GwtRequest;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowBizData;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowMappingInfo;
import com.ruicar.afs.cloud.workflow.greatwall.enums.GwtMsgType;
import com.ruicar.afs.cloud.workflow.greatwall.enums.RequestPath;
import com.ruicar.afs.cloud.workflow.greatwall.feign.GwtWorkFLowFeign;
import com.ruicar.afs.cloud.workflow.greatwall.mapper.AfsGreatWallTaskAssignInfoMapper;
import com.ruicar.afs.cloud.workflow.greatwall.processor.AbsBaseProcessor;
import com.ruicar.afs.cloud.workflow.greatwall.processor.GwtFlowProcessor;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowBizDataService;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowMappingInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@Slf4j
public class UserOnlineProcessor extends AbsBaseProcessor implements GwtFlowProcessor {
    private final AfsGreatWallWorkflowMappingInfoService afsGreatWallWorkflowMappingInfoService;
    private final DynamicRequest dynamicRequest;
    private final AfsGreatWallTaskAssignInfoMapper afsGreatWallTaskAssignInfoMapper;
    private final GwtWorkFLowFeign gwtWorkFLowFeign;

    public UserOnlineProcessor(AfsGreatWallWorkflowBizDataService afsGreatWallWorkflowBizDataService, AfsGreatWallWorkflowMappingInfoService afsGreatWallWorkflowMappingInfoService, DynamicRequest dynamicRequest, AfsGreatWallTaskAssignInfoMapper afsGreatWallTaskAssignInfoMapper, GwtWorkFLowFeign gwtWorkFLowFeign) {
        super(afsGreatWallWorkflowBizDataService);
        this.afsGreatWallWorkflowMappingInfoService = afsGreatWallWorkflowMappingInfoService;
        this.dynamicRequest = dynamicRequest;
        this.afsGreatWallTaskAssignInfoMapper = afsGreatWallTaskAssignInfoMapper;
        this.gwtWorkFLowFeign = gwtWorkFLowFeign;
    }

    @Override
    public GwtMsgType msgType() {
        return GwtMsgType.IS_USER_ONLINE;
    }

    @Override
    public String process(GwtRequest req) {
        log.info("查询用户是否在线===>{}", req);
        checkException(req.getServiceId(), req.getDataId());
        JSONObject rtnObject = new JSONObject();
        rtnObject.put("{@ret}", new JSONArray());
        AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo = afsGreatWallWorkflowMappingInfoService.queryMappingByServiceId(req.getServiceId());
        try {
            if (afsGreatWallWorkflowMappingInfo != null && StringUtils.isNotEmpty(req.getBody())) {
                AfsFlowQueryRequest<UserOnlineRequest> afsFlowQueryRequest = new AfsFlowQueryRequest<>();
                UserOnlineRequest userOnlineRequest = new UserOnlineRequest();
                userOnlineRequest.setUserInfos(Arrays.asList(req.getBody().split(",")).stream().map(name -> new UserOnlineRequest.UserInfo(name, 0L)).collect(Collectors.toList()));
                AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData = afsGreatWallWorkflowBizDataService.getBizDataObjServiceIdAndDataId(req.getServiceId(), req.getDataId());

                if (afsGreatWallWorkflowBizData != null && StringUtils.isNotEmpty(afsGreatWallWorkflowBizData.getFlowInstanceId())) {
                    String flowInstanceInfo = gwtWorkFLowFeign.queryInstance(afsGreatWallWorkflowBizData.getFlowInstanceId());
                    GwtFlowEngineResponse gwtFlowEngineResponse = JSON.parseObject(flowInstanceInfo, GwtFlowEngineResponse.class);
                    if (gwtFlowEngineResponse.getSuccess() == 1) {
                        FlowInstanceBean flowInstanceBean = JSONObject.parseObject(gwtFlowEngineResponse.getData(), FlowInstanceBean.class);
                        String nodeId = flowInstanceBean.getCurrentTaskId();
                        String response = gwtWorkFLowFeign.queryNodeUser(1000L, 1L, nodeId);
                        userOnlineRequest.setNodeId(nodeId);
                        JSONObject jsonObject = JSONObject.parseObject(response);
                        if (jsonObject.getInteger("success") == 1) {
                            List<FLowNodeUserBean> flowNodeBeans = jsonObject.getJSONObject("data").getJSONArray("data").toJavaList(FLowNodeUserBean.class);
                            Map<String, FLowNodeUserBean> taskNodeCount = flowNodeBeans.stream().collect(Collectors.toMap(FLowNodeUserBean::getUserName, Function.identity()));
                            userOnlineRequest.getUserInfos().forEach(userInfo -> {
                                userInfo.setAvailableTaskCount(taskNodeCount.containsKey(userInfo.getUserName()) ? (taskNodeCount.get(userInfo.getUserName()).getWeight() - taskNodeCount.get(userInfo.getUserName()).getTaskCount()) : 0);
                                userInfo.setTaskCount(taskNodeCount.containsKey(userInfo.getUserName()) ? (taskNodeCount.get(userInfo.getUserName()).getTaskCount()) : 0);
                                userInfo.setTotWeight(taskNodeCount.containsKey(userInfo.getUserName()) ? (taskNodeCount.get(userInfo.getUserName()).getTotalWeight()) : 0);
                                userInfo.setWeight(taskNodeCount.containsKey(userInfo.getUserName()) ? (taskNodeCount.get(userInfo.getUserName()).getWeight()) : 0);
                            });
                        }
                    }
                }
                userOnlineRequest.setAfsFlowKey(FlowMappingHelper.getAfsKey(req.getServiceId()));
                userOnlineRequest.setBizDataId(req.getDataId());
                userOnlineRequest.setServiceId(req.getServiceId());
                afsFlowQueryRequest.setAfsFlowKey(afsGreatWallWorkflowMappingInfo.getAfsFlowKey());
                afsFlowQueryRequest.setBizDataId(req.getDataId());
                afsFlowQueryRequest.setData(userOnlineRequest);
                IResponse<List<UserOnlineResponse>> response =
                        dynamicRequest.post(afsGreatWallWorkflowMappingInfo.getServiceName(), AfsEnumUtil.key(RequestPath.CHECK_USER_ONLINE), afsFlowQueryRequest, new TypeReference<List<UserOnlineResponse>>() {
                        });
                Assert.isTrue(CommonConstants.SUCCESS.equalsIgnoreCase(response.getCode()), "feign 查询用户是否在线");
                response.getData()
                        .stream()
                        .filter(UserOnlineResponse::isOnLine)
                        .forEach(userOnlineResponse -> {
                            JSONObject temp = new JSONObject();
                            temp.put("ID", userOnlineResponse.getUserName());
                            rtnObject.getJSONArray("{@ret}").add(temp);
                        });
            }
        } catch (Exception e) {
            log.error("检查用户是否在线失败", e);
        }
        return rtnObject.toJSONString();
    }
}
